﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using hedefgrup.reports.renault.database;
using hedefgrup.reports.renault.date;
using System.Collections;
using hedefgrup.reports.common.SSRD;

namespace hedefgrup.reports.common
{
    public class Report_Standard : Report_Abstract
    {
        internal class Storage
        {
            internal float Count;
            internal SortedList<string, float> Options = new SortedList<string, float>();

            internal void Append(Storage storage)
            {
                Count += storage.Count;
                foreach (string option in storage.Options.Keys)
                {
                    if (Options.ContainsKey(option))
                    {
                        Options[option] += storage.Options[option];
                    }
                    else
                    {
                        Options.Add(option, storage.Options[option]);
                    }
                }
            }
        }

        private SortedList<string, Storage> ModifyStorageAccordingToRoll(SortedList<string, Storage> reportStorage, int roll)
        {
            if (roll == 0)
            {
                return reportStorage;
            }

            reportMonth beginMonth = new reportMonth(GetCriteriaByName("Begin Month").Value);
            reportMonth endMonth = new reportMonth(GetCriteriaByName("End Month").Value);

            SortedList<string, Storage> rolledReportStorage = new SortedList<string, Storage>();

            string[] suffixes = { "", " - BAYİİ" };

            for (int i = 0; i < suffixes.Length; i++)
            {
                string keySuffix = suffixes[i];

                for (int month = endMonth.dateValue; month >= beginMonth.dateValue; month--)
                {
                    if (month % 100 == 0) // 201500 -> 201412
                    {
                        month -= 88;
                    }
                    reportMonth currentMonth = new reportMonth(month);
                    string monthAndYear = currentMonth.ToYYYYMM();

                    if (!reportStorage.ContainsKey(monthAndYear + keySuffix))
                    {
                        if (string.IsNullOrEmpty(keySuffix))
                        {
                            reportStorage.Add(monthAndYear + keySuffix, new Storage());
                        }
                        else
                        {
                            continue;
                        }
                    }

                    Storage currentStorage = reportStorage[monthAndYear + keySuffix];

                    rolledReportStorage.Add(monthAndYear + keySuffix, currentStorage);

                    for (int rollOffset = 1; rollOffset <= roll; rollOffset++)
                    {
                        string rollIncludedMonthAndYear = (currentMonth - rollOffset).ToYYYYMM();
                        if (reportStorage.ContainsKey(rollIncludedMonthAndYear + keySuffix))
                        {
                            currentStorage.Append(reportStorage[rollIncludedMonthAndYear + keySuffix]);
                        }
                    }

                }
            }

            return rolledReportStorage;
        }

        protected virtual DataTable GetYearlyReportData(string questionCode)
        {
            return GetYearlyReportData(questionCode, null);
        }

        protected virtual DataTable GetYearlyReportData(string questionCode, string caseStatement)
        {
            Filter yearFilter = GetFilterByName("YIL");
            string yearFilterValueBackup = yearFilter.Values.Count > 0 ? yearFilter.Values[0] : null;
            yearFilter.Values.Clear();
            yearFilter.Values.Add(GetMaxYearForYearlyTotal().ToString());

            DataTable yearlyData = db.query
            (
                "SELECT YIL = 1, AY = 0, CNT = COUNT(*), " + questionCode + (caseStatement != null ? " = " + caseStatement : "") + " FROM " + Context.TableName + " " +
                GetSqlStatementFilter(new Criteria[] { }) +
                " GROUP BY " + (caseStatement != null ? caseStatement : questionCode),
                base.GetSqlStatementParameters(new Criteria[] { })
            );

            if (yearFilterValueBackup != null)
            {
                yearFilter.Values[0] = yearFilterValueBackup;
            }
            else
            {
                yearFilter.Values.Clear();
            }
            return yearlyData;
        }

        protected virtual DataTable GetReportData(string questionCode)
        {
            return GetReportData(questionCode, null);
        }

        protected virtual DataTable GetReportData(string questionCode, string caseStatement)
        {
            return db.query
            (
                "SELECT YIL, AY, CNT = COUNT(*), " + questionCode + (caseStatement != null ? " = " + caseStatement : "") + ", " + base.DealerColumn + " FROM " + Context.TableName + " " +
                GetSqlStatementFilter() +
                " GROUP BY " + base.DealerColumn + ", YIL, AY, " + (caseStatement != null ? caseStatement : questionCode) + " ",
                base.GetSqlStatementParameters()
            );
        }

        protected void AppendQuestion(string questionCode, ReportResult results)
        {
            AppendQuestion(questionCode, null, results);
        }

        protected virtual string GetYearlyTotalColumnHeader()
        {
            return string.Format("{0}YTD", GetMaxYearForYearlyTotal());
        }

        protected void AppendQuestion(string questionCode, string caseStatement, ReportResult results)
        {
            DataTable yearData = GetYearlyReportData(questionCode, caseStatement);

            DataTable reportData = GetReportData(questionCode, caseStatement);

            List<string> optionList = new List<string>();

            SortedList<string, Storage> allStorages = ToStorage(yearData, questionCode, optionList, true);
            Storage thisYearsStorage = allStorages.Count > 0 ? allStorages.Values[0] : null;

            SortedList<string, Storage> reportStorage = ToStorage(reportData, questionCode, optionList, false);

            int roll = 0;
            if (GetCriteriaByName("Roll") != null)
            {
                roll = (int)GetCriteriaByName("Roll").ToActualValue();
            }

            reportStorage = ModifyStorageAccordingToRoll(reportStorage, roll);

            Tree question = Context.Questionnaire.GetChild(questionCode);

            Row headerRow = new Row();
            if (results.HeaderRows.Count == 0)
            {
                results.HeaderRows.Add(headerRow);
            }
            else
            {
                results.Rows.Add(headerRow);
            }
            headerRow.Cells.Add(new Cell());
            headerRow.Cells.Add(new Cell() { Text = GetYearlyTotalColumnHeader(), Bold = true });
            headerRow.Cells.Add(new Cell() { Text = GetYearlyTotalColumnHeader(), Bold = true });
            foreach (string yearMonth in reportStorage.Keys)
            {
                if (GetCriteriaByName("SSM Period") != null && GetCriteriaByName("SSM Period").Value != Criteria_SSRD_SSMPeriod.PleaseSelect)
                {
                    headerRow.Cells.Add(new Cell() { Text = GetCriteriaByName("SSM Period").Value, Bold = true });
                    headerRow.Cells.Add(new Cell() { Text = GetCriteriaByName("SSM Period").Value, Bold = true });
                }
                else
                {
                    headerRow.Cells.Add(new Cell() { Text = yearMonth, Bold = true });
                    headerRow.Cells.Add(new Cell() { Text = yearMonth, Bold = true });
                }
            }

            Row valueHeaderRow = new Row();
            if (results.HeaderRows.Count == 1)
            {
                results.HeaderRows.Add(valueHeaderRow);
            }
            else
            {
                results.Rows.Add(valueHeaderRow);
            }
            valueHeaderRow.Cells.Add(new Cell());
            for (int i = 0; i < 1 + reportStorage.Count; i++)
            {
                valueHeaderRow.Cells.Add(new Cell() { Text = "Baz", Bold = true });
                valueHeaderRow.Cells.Add(new Cell() { Text = "%", Bold = true });
            }

            Row questionHeaderRow = new Row();
            results.Rows.Add(questionHeaderRow);
            questionHeaderRow.Cells.Add(new Cell() { Text = questionCode + " - " + question["Text"], TextAlign = "left", Bold = true });
            questionHeaderRow.Cells.Add(new Cell() { Text = thisYearsStorage != null ? thisYearsStorage.Count.ToString() : "0" });
            questionHeaderRow.Cells.Add(new Cell() { Text = thisYearsStorage != null ? thisYearsStorage.Count.ToString() : "0" });
            foreach (Storage storage in reportStorage.Values)
            {
                questionHeaderRow.Cells.Add(new Cell() { Text = storage.Count.ToString() });
                questionHeaderRow.Cells.Add(new Cell() { Text = storage.Count.ToString() });
            }

            optionList.Sort();

            foreach (string option in optionList)
            {
                Row optionRow = new Row();

                Tree optionTree = question.GetChild(option);

                if (optionTree != null && optionTree["OptionGroupHeader"] != null)
                {
                    Row optionGroupHeaderRow = new Row();
                    Cell optionGroupHeaderCell = new Cell() { Text = optionTree["OptionGroupHeader"], Span = 2 + reportStorage.Count * 2 + 1, Bold = true, TextAlign = "left" };
                    optionGroupHeaderRow.Cells.Add(optionGroupHeaderCell);
                    results.Rows.Add(optionGroupHeaderRow);
                }

                results.Rows.Add(optionRow);

                optionRow.Cells.Add(new Cell() { Text = option + " - " + (optionTree != null ? optionTree["Text"] : option), TextAlign = "left" });

                if (thisYearsStorage != null && thisYearsStorage.Options.ContainsKey(option))
                {
                    optionRow.Cells.Add(new Cell() { Text = thisYearsStorage.Options[option].ToString() });
                    optionRow.Cells.Add(new Cell() { Text = string.Format("{0:0.0}", 100 * (thisYearsStorage.Options[option] / thisYearsStorage.Count)) });
                }
                else
                {
                    optionRow.Cells.Add(new Cell() { Text = "" });
                    optionRow.Cells.Add(new Cell() { Text = "" });
                }

                foreach (Storage storage in reportStorage.Values)
                {
                    if (storage.Options.ContainsKey(option))
                    {
                        optionRow.Cells.Add(new Cell() { Text = storage.Options[option].ToString() });
                        optionRow.Cells.Add(new Cell() { Text = string.Format("{0:0.0}", 100 * (storage.Options[option] / storage.Count)) });
                    }
                    else
                    {
                        optionRow.Cells.Add(new Cell() { Text = "" });
                        optionRow.Cells.Add(new Cell() { Text = "" });
                    }
                }
            }

            results.Rows.Add(new Row());
        }

        private SortedList<string, Storage> ToStorage(DataTable reportData, string questionCode, List<string> optionList, bool ignoreAuthorization)
        {
            SortedList<string, Storage> storage = new SortedList<string, Storage>();

            foreach (DataRow reportRow in reportData.Rows)
            {
                string yearMonth = string.Format("{0:0000}{1:00}", reportRow["YIL"], reportRow["AY"]);
                string yearMonthDealer = string.Format("{0:0000}{1:00} - BAYİİ", reportRow["YIL"], reportRow["AY"]);

                List<string> authorizedDealers = Static.GetAuthorizedDealers(this);

                if (authorizedDealers == null || authorizedDealers.Count == 0)
                {
                    ignoreAuthorization = true;
                }

                Storage currentStorage = null;
                Storage currentStorageDealer = null;

                if (!storage.ContainsKey(yearMonth))
                {
                    storage.Add(yearMonth, currentStorage = new Storage());
                    if (!ignoreAuthorization)
                    {
                        storage.Add(yearMonthDealer, currentStorageDealer = new Storage());
                    }
                }
                else
                {
                    currentStorage = storage[yearMonth];
                    if (!ignoreAuthorization)
                    {
                        currentStorageDealer = storage[yearMonthDealer];
                    }
                }

                string optionsString = reportRow[questionCode].ToString();

                if (!string.IsNullOrEmpty(optionsString))
                {
                    int count = Convert.ToInt32(reportRow["CNT"]);
                    currentStorage.Count += count;
                    string dealerCode = null;
                    if (!ignoreAuthorization)
                    {
                        dealerCode = reportRow[base.DealerColumn].ToString().Trim();
                        if (authorizedDealers.Contains(dealerCode))
                        {
                            currentStorageDealer.Count += count;
                        }
                    }
                    string[] options = optionsString.Split(',');
                    foreach (string option in options)
                    {
                        string optionTrimmed = option.Trim();
                        if (!string.IsNullOrEmpty(optionTrimmed))
                        {
                            AppendOptions(optionList, currentStorage, count, optionTrimmed);
                            if (!ignoreAuthorization)
                            {
                                if (authorizedDealers.Contains(dealerCode))
                                {
                                    AppendOptions(optionList, currentStorageDealer, count, optionTrimmed);
                                }
                            }
                        }
                    }
                }
            }

            return storage;
        }

        private static void AppendOptions(List<string> optionList, Storage currentStorage, int count, string optionTrimmed)
        {
            if (!currentStorage.Options.ContainsKey(optionTrimmed))
            {
                currentStorage.Options.Add(optionTrimmed, count);
            }
            else
            {
                currentStorage.Options[optionTrimmed] += count;
            }
            if (!optionList.Contains(optionTrimmed))
            {
                optionList.Add(optionTrimmed);
            }
        }

        protected override void SetCriteriaList()
        {
            if (GetType() == typeof(Report_Standard))
            {
                Criterias.Add(new Criteria_Roll() { Context = Context });
                Criterias.Add(new Criteria_BeginMonth() { Context = Context });
                Criterias.Add(new Criteria_EndMonth() { Context = Context });
                Criterias.Add(new Criteria_Network() { Context = Context });
            }
            else
            {
                base.SetCriteriaList();
            }
        }

        public override ReportResult GenerateReport()
        {
            ReportResult results = new ReportResult(this);

            if (Context.CompatibleProjectName == Global.PROJECT_QVN2013)
            {
                AppendQuestion("S18", results);

                AppendQuestion("S17", results);

                AppendQuestion("S17a", results);
            }
            else
            {
                bool isCoordinator = base.GetAuthLevel() == "coordinator";
                bool isDealer = base.GetAuthLevel() == "dealer";
                AppendQuestion("S2", results);
                if (!isCoordinator && !isDealer)
                {
                    AppendQuestion("S3b", results);
                }

                AppendQuestion("S4_1", results);
                AppendQuestion("S4", results);
                AppendQuestion("S4_1_S41_1", "CASE WHEN S4 = 1 OR S4_1 = 1 THEN 1 ELSE 2 END", results);

                AppendQuestion("S6", results);
                if (!isCoordinator && !isDealer)
                {
                    AppendQuestion("S6_2", results);
                }
                AppendQuestion("S7", results);
                AppendQuestion("S7A", results);
                AppendQuestion("S8", results);
                AppendQuestion("S8b", results);
                if (!isCoordinator && !isDealer)
                {
                    AppendQuestion("S11", results);
                }
            }

            return results;
        }

        public override string DisplayName
        {
            get { return "Standart Ekran - Renault - Dacia"; }
        }

        public override bool SupportsProject(string projectName)
        {
            return base.SupportsProject(projectName) || projectName == Global.PROJECT_SATIS_SUREC;
        }

        public override string SortPrefix
        {
            get { return "0x00"; }
        }
    }
}
